/**
 * 辅助函数，用于深拷贝对象
 * @param {Object} obj
 * @returns
 */
function deepClone(obj) {
  if (Array.isArray(obj)) {
    return obj.map((it) => deepClone(it));
  } else if (typeof obj === "object") {
    const result = {};
    for (let key in obj) {
      result[key] = deepClone(obj[key]);
    }
    return result;
  } else {
    return obj;
  }
}

/**
 * TODO: 待补充代码 目标 4
 * @param {Ref} someRef Vue的某个ref对象，需要对传入的ref对象的历史状态做记录
 * @returns 返回一个对象，其中包含函数 undo 和 redo； undo 表示撤销，比如给 someRef 设置一个新状态后，调用 undo 可以将 someRef 还原为上一个旧状态；同理，在旧状态调用 redo 可以将 someRef 恢复为新状态
 */
function useRefHistory(someRef) {
  const { ref, watch } = Vue;
  const history = []; // 用于储存历史记录
  let currentIndex = -1; // 当前状态的索引
  let flag = false; // 用于判断是否是 undo/redo 方法中改变的

  // 监听someRef 的变化
  watch(
    someRef,
    (newVal) => {
      // 如果是 undo/redo 中触发的改变，不记录历史
      if (flag) {
        flag = false;
        return;
      }
      // -----下面不是 undo/redo 中触发的改变-----
      // 如果当前索引不在末尾，删除未来历史
      if (currentIndex > 1) {
        history.splice(currentIndex + 1);
      }

      // 保存新状态
      history.push(deepClone(newVal));
      currentIndex = history.length - 1; // 指向最新状态
    },
    { deep: true, immediate: true }
  );
  function undo() {
    /**
     * 调用 undo 时，将 someRef 撤销为上一个状态
     */
    if (currentIndex > 0) {
      // 修改 undo/redo 改变标识
      flag = true;
      // 撤销则为 下标 -1
      currentIndex--;
      // 拷贝赋值
      someRef.value = deepClone(history[currentIndex]);
    }
  }
  function redo() {
    /**
     * 调用 redo 时，将 someRef 恢复为下一个状态
     */
    if (currentIndex < history.length - 1) {
      // 修改 undo/redo 改变标识
      flag = true;
      // 恢复 则为 +1
      currentIndex++;
      // 拷贝赋值
      someRef.value = deepClone(history[currentIndex]);
    }
  }

  return {
    undo,
    redo,
  };
}
